home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1996 #15 / Monster Media Number 15 (Monster Media)(July 1996).ISO / prog_c / cuj0896.zip / KREHBIEL.ZIP / PCX.C < prev    next >
C/C++ Source or Header  |  1996-04-15  |  5KB  |  192 lines

  1. Listing 4:
  2. /*--------------------------------------------------------------
  3.   pcx.c               Mode 101h PCX Viewer                  1.0
  4. ----------------------------------------------------------------
  5.  
  6.   Program:    views VESA mode 0x101 (640x480x256) PCX files.
  7.   
  8.   Usage:    PCX <filename>
  9.     
  10.   Build:     pcx.c,vbe.c,vbe.h -> pcx.exe
  11.   
  12.   Platform:    IBMPC,MSDOS.
  13.  
  14.   Functions:
  15.       ReadPalette        Reads the palette block of a PCX file.
  16.       ReadHeader        Reads the header block of a PCX file.
  17.       ReadLine        Reads one scanline from a PCX file.
  18.     PcxShowFile        Reads and displays a PCX file.
  19.     PcxDeinit        Restores video to text mode.
  20.     main            Program entry point.
  21.     
  22.   Edit History:
  23.     04/12/96    C.Krehbiel.  Implemented pcx.c in MSVC 1.0,
  24.                   medium memory model, for MS-DOS.
  25.  
  26. --------------------------------------------------------------*/
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31.  
  32. #include <conio.h>
  33. #include <dos.h>
  34.  
  35. #include "vbe.h"    /* vesa vbe interface */
  36.  
  37. /*--------------------------------------------------------------
  38.                           Local Data
  39. --------------------------------------------------------------*/
  40.  
  41. typedef struct    /* (Abridged) header record of a PCX file */
  42. {
  43.     char    Manufacturer;    /* pcx file signature: 10 */
  44.     char    Version;        /* pc paintbrush version */
  45.     char    Encoding;        /* 1: rle */
  46.     char    BitsPerPixel;    /* color resolution */
  47.     int        Xmin,Ymin;        /* image origin */
  48.     int        Xmax,Ymax;        /* image extent */
  49.     char    NotUsed1[53];    /* not used by this program */
  50.     char    Planes;            /* number of color planes */
  51.     int        BytesPerLine;    /* (per plane) */
  52.     char    NotUsed2[58];    /* not used by this program */
  53.     
  54. } pcx_t;
  55.  
  56. enum    /* Error codes; also index ErrorText array below */
  57. {
  58.     PCX_OK,PCX_EOPEN,PCX_EVIDEO,PCX_EREAD,PCX_EFORMAT
  59. };
  60.  
  61. static const char *ErrorText[]=
  62. {
  63.     /* PCX_OK */        "Ok",
  64.     /* PCX_EOPEN */        "File not found",
  65.     /* PCX_EVIDEO */    "Unsupported video mode",
  66.     /* PCX_EREAD */        "File read error",
  67.     /* PCX_EFORMAT */    "Invalid or unsupported format"
  68. };
  69.  
  70. static char    Line[640];            /* PCX image line buffer */
  71. static char    Palette256[768];    /* DAC palette data */
  72. static pcx_t Header;            /* PCX file header record */
  73.  
  74.  
  75. /*--------------------------------------------------------------
  76.                    local pcx file functions
  77. --------------------------------------------------------------*/
  78. static int ReadHeader(FILE *f)
  79.  
  80.     /* reads the header of the open file into the global Header
  81.     structure; returns 0 on a file read error, or if the file 
  82.     is not a valid pcx file, or if the pcx file does not contain 
  83.     a 640x480x256-compatible image. */
  84. {
  85.     pcx_t *h=&Header;
  86.     
  87.     fread(h,sizeof(pcx_t),1,f);
  88.  
  89.     return !(ferror(f) ||                        
  90.         h->Manufacturer!=10 || h->Encoding!=1 ||
  91.         h->Planes!=1 || h->BitsPerPixel!=8 ||
  92.         h->Ymax-h->Ymin>479 || h->Xmax-h->Xmin>639);
  93. }
  94. static int ReadPalette(FILE *f)
  95.     
  96.     /* reads the 256-color palette of the open file into the 
  97.     global buffer Palette256, and converts it to 6-bit DAC 
  98.     palette register data; returns 0 on a file read error or an
  99.     invalid palette block. */
  100. {
  101.     int i;
  102.     
  103.     fseek(f,-769L,SEEK_END);        /* to palette block */
  104.     if(fgetc(f)!=12) return 0;        /* check signature byte */
  105.     fread(Palette256,768,1,f);        /* read the 256 triplets */
  106.     if(ferror(f)) return 0;
  107.     fseek(f,128L,SEEK_SET);            /* back to image data */    
  108.     
  109.     for(i=0;i<768;i++) Palette256[i]>>=2;    /* to 6-bit rgb */
  110.     return 1;
  111.  
  112. }
  113. static void ReadLine(FILE *f)
  114.  
  115.     /* reads and decompresses the next scanline from the current
  116.     pcx file into the global Line buffer. */
  117. {
  118.     int    c,i=0;
  119.     
  120.     while(i<Header.BytesPerLine)
  121.     {
  122.         c=fgetc(f);
  123.         if((c&0xc0)==0xc0)        /* byte is rle block header */
  124.         {
  125.             c&=~0xc0;                    /* =repeat count */
  126.             memset(Line+i,fgetc(f),c);    /* =pixel data */
  127.             i+=c;
  128.         }
  129.         else Line[i++]=c;        /* byte is pixel data */
  130.     }
  131.      return;
  132.      
  133. }
  134. /*--------------------------------------------------------------
  135.                        general functions
  136. --------------------------------------------------------------*/
  137. int PcxShowFile(const char *file)
  138.  
  139.     /* reads and displays a pcx file; returns 0 on success,
  140.     PCX_ error code on failure. */
  141. {
  142.     int    e=PCX_OK;
  143.     FILE *f=fopen(file,"rb");
  144.  
  145.     if(!f) e=PCX_EOPEN;
  146.     else if(!ReadHeader(f)) e=PCX_EFORMAT;
  147.     else if(Header.Version==5 && !ReadPalette(f)) e=PCX_EFORMAT;
  148.     else if(!VbeSetMode(0x101)) e=PCX_EVIDEO;
  149.     else
  150.     {
  151.         int y,ymax=min(Header.Ymax,479);
  152.         int    n=min(Header.Xmax,640)-Header.Xmin+1;
  153.         
  154.         if(Header.Version==5) VbeSetPalette(Palette256,0,256);
  155.  
  156.         for(y=Header.Ymin;y<ymax;y++)
  157.         {
  158.             ReadLine(f);
  159.             VbeWrite(Header.Xmin,y,n,Line);
  160.         }
  161.     }
  162.     if(f) fclose(f);
  163.     return e;
  164.     
  165. void PcxDeinit()
  166.  
  167.     /* clears the image and resets the video to standard 
  168.     80-column text mode */
  169. {
  170.     VbeSetMode(3);
  171. }
  172. void main(int argc,char **argv)
  173.  
  174.     /* displays the pcx file specified by the first argument to 
  175.     the    program (usage: PCX <filename>) */
  176. {
  177.     int e=PcxShowFile(argv[1]);
  178.     
  179.     if(!e)
  180.     {
  181.         getch();
  182.         PcxDeinit();
  183.     }
  184.     else puts(ErrorText[e]);
  185.     
  186. } /* main */
  187.  
  188. /*--------------------------------------------------------------------------
  189.                                     eof
  190. --------------------------------------------------------------------------*/
  191.